home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
c
/
dice-3.16.lha
/
doc
/
romable.doc
< prev
next >
Wrap
Text File
|
1994-02-13
|
16KB
|
438 lines
romable/romable romable/romable
ROMABLE.DOC
GENERATING ROMABLE FIRMWARE
REFERENCES
Please refer to the following DCC options:
-pi generate position independant code. All code references
forced to PC-relative
-pr generate residentable position independant code. Unless
-mw is specified A4 relative addressing is used for data
items. All code references forced to PC-relative.
-ma specify that initialized data + bss will be hardwired to
a known address
-mw specify that initialized data + bss will be hardwired to
a known address and all of data + bss occurs somewhere
within the first 32KBytes of the address space
(0x0000-0x7FFF). Also allows DICE to use A4 as a register
variable.
-ms const items go into EPROM in local cases
-mS const items go into EPROM in local and external cases
The following documentation may appear confusing, but only because so
many possibilities exist when one intends to put code in ROM. When you
are in doubt, it is usually a good idea to write a small test source
file, compile it, link it with symbols, and then look at the resulting
executable with DOBJ.
MAKING ROMABLE PROGRAMS
DICE has the capability to generate ROMABLE programs. That is, program
binaries that you can use to directly burn an EPROM. When generating
ROMABLE code you have more data model options available to you. The
basic idea of ROMd code is as follows:
________________
FIXED ADDRESS = EPROM | |
| 68000 vectors | const data objects
|----------------|
| CODE |
|----------------|
| const DATA | string constants and other
| | const items, stays in eprom.
|----------------|
| read-only copy |
| of initialized | this is copied to a working
| data | RAM copy by the reset code
|________________|
________________
FIXED ADDRESS = RAM | run-time copy | (copied from EPROM by startup)
| of initialized |
| data |
|----------------| (cleared by EPROM startup)
| run-time BSS |
|________________|
From the above you have two basic choices in terms of where your
RUN-TIME DATA is based. If your RAM exists in low-memory
(0x0000-0x7FFF) you may choose to compile your code to use the
ABSOLUTE-WORD addressing mode. This modes takes the same space as the
A4-RELATIVE addressing mode yet does not require use of the A4 register
and, in fact, the A4 register will then be available for use as a
register variable.
If you have minimal RAM in low-memory or your DATA+BSS is larger than
32KBytes (yes, that's 32KBytes people, not 64KBytes), then you will
have to choose either the formal large-data model or the A4-relative
small data model. If you initialized data is over 64KBytes you can
still use the small-data model for most objects by using the __far
keyword judiciously.
NOTE: in all cases you can allocate or generate points for any ram
location, this just refers to accesses of declared variables! Pointers
are always 32 bits.
model options advantages disadvantages
absolute-word -mw -ms no need for A4 low 32KBytes only
A4 available as
reg variable
small-data -ma -ms RAM can be anywhere requires A4
must use __geta4
large-data -ma -mD -ms RAM can be anywhere code is larger
libs must all be
large-data
CODE MODEL
The CODE MODEL is normally left at PC-relative and should not present a
problem.
CONST DATA
You want to use the -ms option or even the -mS option (see DCC.DOC for
the differences). This will place all string constants in EPROM and
IN THE CODE SEGMENT, thus this initialized data will NOT take up space
in RAM. Any 'const' initialized data will be placed in the code segment
and thus in EPROM. Any non-const initialized data will be copied from
EPROM into RAM by your reset-startup code.
Any tables that you declare that you will never modify should be
declared const so they reside in EPROM and do not take up space in RAM.
On the otherhand, if your EPROM is running 6 wait states and your RAM
is running 0 you might consider not using 'const'.... assuming you have
a lot of RAM.
When your code is less than 32KBytes big you can use -pi or -pr and
should definitely use -mS. When your code is larger than 32KBytes you
cannot use -mS unless you are absolutely positive pc-relative const
data references do not exceed the word-relative range.
RESET VECTOR, DATA MODEL SETUP
If your EPROM is mapped into low memory on boot you can declare a vector
table by declaring a CONST LONG array as the first data object in the
first object module that you link to create the executable:
const long ROMVectorTable[] = {
InitialSSP,
ResetVector,
.
.
.
};
Remember, this must be the first data declaration in the first object
module!!! If you are using the A4-RELATIVE small-data model you must
qualify your ResetVector with the __geta4 type qualifier to set up A4.
In most cases you will want ResetVector to point to some assembly which
initializes your RAM DATA & BSS before calling C code. The assembly
normally looks like this (this would be the second object in the link):
; RESET exception, copy initialized data to RAM and clear
; BSS area before calling rom_main()
;
; Assumes less than 256KBytes of data and 256KBytes of BSS
xref __DATA_BAS ; linker generated symbols
xref __ABSOLUTE_BAS
xref __DATA_LEN
xref __BSS_LEN
xref _rom_main
_ResetVector
lea __DATA_BAS,A0 ; ROM data
lea __ABSOLUTE_BAS,A1 ; RAM data
move.w #__DATA_LEN,D0 ; long words of data
bra trentry
trloop move.l (A0)+,(A1)+ ; copy EPROM copy to run-time
trentry dbf D0,trloop ; RAM copy.
move.w #__BSS_LEN,D0 ; long words of BSS (follows data)
moveq.l #0,D1
bra trbentry
trbloop move.l D1,(A1)+ ; clear run-time RAM
trbentry dbf D0,trbloop
jmp _rom_main(pc)
Where rom_main() is your C main routine qualified with __geta4 (if you
are using the A4-RELATIVE data model). Any special items, such as
the EPROM getting mapped at reset, must be dealt with as well, usually
before the reset code sets up the run-time enviroment.
If you are using the ABSOLUTE-WORD data model DO NOT USE __GETA4!
Specifically, the -mw option TELLS DICE THAT A4 IS FREE FOR USE AS A
NORMAL REGISTER VARIABLE. This gives you an extra register variable if
you haven't guessed!
EXAMPLE PROGRAM
Assume the above assembly module has been assembled and is called
'romc.o'. The following C program is called 'test.c'. In all cases
the code may start anywhere.
Also, in all cases note that ROMC.O is specified AFTER test in the
DCC line (that also serves as the link line). This is because for
a standalone product we want our CONST data object that is the
ROM VECTOR TABLE to be first. Of course, if you put the ROM VECTOR
TABLE in ROMC.A instead of TEST.C then ROMC.A would go first. To
put the ROM VECTOR TABLE in ROMC.A it should be the first data
object declarations (dc.l's) in the CODE segment.
(1) SMALL-DATA-MODEL
extern void TrapReset();
extern char SSp[512];
const long RomVectors[] = { (long)SSp, (long)TrapReset };
char SSp[512]; /* our supervisor stack in BSS */
__geta4 void
rom_main()
{
short i;
for (;;) {
for (i = 0; i < 10000; ++i) {
<do something here with i>
}
}
}
note, ram can be beyond 64K
v
COMPILE: dcc test.c romc.o -ma 0x10000 -o t:test -r -v -lrom
romable t:test -o t:test.bin -D 0x10000 -C 0x0
burn eprom using test.bin
(2) ABSOLUTE WORD DATA MODEL
The source code is the same except you do not need __geta4. Here
I am assuming RAM starts at, say, 0x2000.
void
rom_main()
{
...
}